/**
 * 
 */
package com.dalonedrow.engine.sprite.impl;

import com.dalonedrow.engine.sprite.base.FontsheetObject;
import com.dalonedrow.engine.sprite.base.SimpleVector3;
import com.dalonedrow.engine.sprite.base.SpriteBase;
import com.dalonedrow.engine.sprite.base.SpriteBaseImpl;
import com.dalonedrow.engine.systems.GameFont;
import com.dalonedrow.engine.ui.base.GuiComponent;
import com.dalonedrow.engine.ui.base.LineOfText;

/**
 * @author Donald
 */
public final class GroupOfText extends SpriteBaseImpl {
	/** the length of the rendering array. */
	private final int			floatLen	= 32;
	/** storage array for rendering values. */
	private float[]			floatStore	= new float[floatLen];
	/** the font reference id. */
	private int				fontRefId;
	/** the full value of the Height. */
	private int				fullHeight;
	/** the full value of the texture's bottom coordinates. */
	private float			fullTcBottom;
	/** the full value of the texture's left coordinates. */
	private float			fullTcLeft;
	/** the full value of the texture's right coordinates. */
	private float			fullTcRight;
	/** the full value of the texture's top coordinates. */
	private float			fullTcTop;
	/** the full value of the Width. */
	private int				fullWidth;
	/** the full value of the {@link SpriteBase}'s Xl position. */
	private float			fullXl;
	/** the full value of the {@link SpriteBase}'s Xr position. */
	private float			fullXr;
	/** the full value of the {@link SpriteBase}'s Yb position. */
	private float			fullYb;
	/** the full value of the {@link SpriteBase}'s Yt position. */
	private float			fullYt;
	/** the group of lines. */
	private LineOfText[]	lines		= new LineOfText[0];
	/**
	 * the value of all modifications applied to the texture's bottom
	 * coordinates.
	 */
	private float			modTcBottom;
	/**
	 * the value of all modifications applied to the texture's left coordinates.
	 */
	private float			modTcLeft;
	/**
	 * the value of all modifications applied to the texture's right
	 * coordinates.
	 */
	private float			modTcRight;
	/** 
	 * the value of all modifications applied to the texture's top coordinates. 
	 */
	private float			modTcTop;
	/**
	 * the value of all modifications applied to the {@link SpriteBase}'s Xl
	 * position.
	 */
	private float			modXl;
	/**
	 * the value of all modifications applied to the {@link SpriteBase}'s Xr
	 * position.
	 */
	private float			modXr;
	/**
	 * the value of all modifications applied to the {@link SpriteBase}'s Yb
	 * position.
	 */
	private float			modYb;
	/**
	 * the value of all modifications applied to the {@link SpriteBase}'s Yt
	 * position.
	 */
	private float			modYt;
	/** the number of lines in the group. */
	private int				numLines;
	/** the position. */
	private SimpleVector3			position;
	/** the value of the texture's bottom coordinates. */
	private float			tcBottom;
	/** the value of the texture's left coordinates. */
	private float			tcLeft;
	/** the value of the texture's right coordinates. */
	private float			tcRight;
	/** the value of the texture's top coordinates. */
	private float			tcTop;
	/**
	 * Adds a line of text.
	 * @param width the width in which the text will be formatted
	 * @param alignment the text alignment
	 * @param text the text
	 * @throws Exception if an error occurs
	 */
	public void addLine(final int width, final int alignment, final String text)
			throws Exception {
		if (super.isDebug()) {
			System.out.println("addLine(" + width + "," + alignment + ", " 
					+ text);
		}
		int index = getIndexOfNextEmptyLine();
		LineOfText line = lines[index];
		if (super.isDebug()) {
			line.setDebug(true);
		}
		line.formatText(width, alignment, text, fontRefId);
		numLines++;
		if (super.isDebug()) {
			System.out.println("adding new line::\"" + text 
					+ "\". now at " + numLines);
			System.out.println("array size::" + lines.length);
			System.out.println(Thread.currentThread().getName());
		}
		int totalchar = 0;
		for (int i = 0; i < numLines; i++) {
			try {
				totalchar += lines[i].getNumberOfCharacters();
			} catch (Exception ex) {
				System.out.println("error with text:\n" + text);
				System.out.println("trying to get line index " + i
						+ " but lines has " + lines.length + " lines");
				System.out.println("but think there are " + numLines
						+ " lines");
				throw ex;
			}
		}
		if (floatStore.length < totalchar * floatLen) {
			floatStore = new float[totalchar * floatLen];
		}
		super.setFloatStoreNumber(0);
	}
	/** Clears all lines. */
	public void clearLines() {
		for (int i = 0; i < lines.length; i++) {
			lines[i].clear();
		}
		numLines = 0;
		if (super.isDebug()) {
			System.out.println("cleared numLines::" + numLines);
			System.out.println("array size::" + lines.length);
		}
		super.setFloatStoreNumber(0);
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public float[] getFloatStore() {
		return floatStore;
	}
	/**
	 * Gets the font reference id.
	 * @return {@link int}
	 */
	public int getFontRefId() {
		return fontRefId;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public int getFullHeight() {
		return fullHeight;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public float getFullTCBottom() {
		return fullTcBottom;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public float getFullTCLeft() {
		return fullTcLeft;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public float getFullTCRight() {
		return fullTcRight;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public float getFullTCTop() {
		return fullTcTop;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public int getFullWidth() {
		return fullWidth;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public float getFullX1() {
		// TODO Auto-generated method stub
		return 0;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public float getFullX2() {
		// TODO Auto-generated method stub
		return 0;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public float getFullX3() {
		// TODO Auto-generated method stub
		return 0;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public float getFullXl() {
		return fullXl;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public float getFullXr() {
		return fullXr;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public float getFullY1() {
		// TODO Auto-generated method stub
		return 0;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public float getFullY2() {
		// TODO Auto-generated method stub
		return 0;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public float getFullY3() {
		// TODO Auto-generated method stub
		return 0;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public float getFullYb() {
		return fullYb;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public float getFullYt() {
		return fullYt;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public int getHeight() {
		// TODO Auto-generated method stub
		return 0;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public int getImageRefId() {
		// TODO Auto-generated method stub
		return 0;
	}
	/**
	 * Gets the array index of the next empty {@link LineOfText} instance.
	 * @return <code>int</code>
	 */
	public int getIndexOfNextEmptyLine() {
		int index = -1;
		// look for a line that doesn't exist
		for (int i = 0; i < lines.length; i++) {
			if (!lines[i].exists()) {
				index = i;
				break;
			}
		}
		if (index == -1) {
			index = lines.length;
			// extend the lines array
			LineOfText[] dest = new LineOfText[lines.length + 1];
			System.arraycopy(lines, 0, dest, 0, lines.length);
			dest[lines.length] = new LineOfText();
			lines = dest;
			dest = null;
		}
		return index;
	}
	public LineOfText getLine(final int lineNumber) throws Exception {
		return lines[lineNumber];
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public int getModHeight() {
		// TODO Auto-generated method stub
		return 0;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public float getModTCBottom() {
		return modTcBottom;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public float getModTCLeft() {
		return modTcLeft;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public float getModTCRight() {
		return modTcRight;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public float getModTCTop() {
		return modTcTop;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public int getModWidth() {
		// TODO Auto-generated method stub
		return 0;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public float getModXl() {
		return modXl;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public float getModXr() {
		return modXr;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public float getModYb() {
		return modYb;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public float getModYt() {
		return modYt;
	}
	public int getNumberOfLines() {
		return numLines;
	}
	public int getNumCharacters() throws Exception {
		int total = 0;
		for (int i = 0; i < numLines; i++) {
			try {
				total += lines[i].getNumberOfCharacters();
			} catch (Exception ex) {
				System.out.println("error with getNumCharacters");
				System.out.println("trying to get line index " + i
							+ " but lines has " + lines.length + " lines");
				System.out.println("but think there are " + numLines
							+ " lines");
				throw ex;
			}
		}
		return total;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public SimpleVector3 getPosition() {
		return position;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public float getTCBottom() {
		return tcBottom;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public float getTCLeft() {
		return tcLeft;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public float getTCRight() {
		return tcRight;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public float getTCTop() {
		return tcTop;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public int getType() {
		return SpriteBase.TYPE_03_GROUP_TEXT;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public int getWidth() {
		// TODO Auto-generated method stub
		return 0;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public float getX1() {
		// TODO Auto-generated method stub
		return 0;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public float getX2() {
		// TODO Auto-generated method stub
		return 0;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public float getX3() {
		// TODO Auto-generated method stub
		return 0;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public float getY1() {
		// TODO Auto-generated method stub
		return 0;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public float getY2() {
		// TODO Auto-generated method stub
		return 0;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public float getY3() {
		// TODO Auto-generated method stub
		return 0;
	}
	/**
	 * Sets the font reference id.
	 * @param val the id to set
	 */
	public void setFontRefId(final int val) {
		fontRefId = val;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void setFullHeight(final int h) {
		fullHeight = h;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void setFullTCBottom(final float val) {
		fullTcBottom = val;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void setFullTCLeft(final float val) {
		fullTcLeft = val;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void setFullTCRight(final float val) {
		fullTcRight = val;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void setFullTCTop(final float val) {
		fullTcTop = val;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void setFullWidth(final int w) {
		fullWidth = w;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void setFullX1(final float val) {
		// TODO Auto-generated method stub

	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void setFullX2(final float val) {
		// TODO Auto-generated method stub

	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void setFullX3(final float val) {
		// TODO Auto-generated method stub

	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void setFullXl(final float val) {
		fullXl = val;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void setFullXr(final float val) {
		fullXr = val;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void setFullY1(final float val) {
		// TODO Auto-generated method stub

	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void setFullY2(final float val) {
		// TODO Auto-generated method stub

	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void setFullY3(final float val) {
		// TODO Auto-generated method stub

	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void setFullYb(final float val) {
		fullYb = val;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void setFullYt(final float val) {
		fullYt = val;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void setHeight(final int h) {
		// TODO Auto-generated method stub

	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void setImageRefId(final int refId) {
		// TODO Auto-generated method stub

	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void setModHeight(final int h) {
		// TODO Auto-generated method stub

	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void setModTCBottom(final float val) {
		modTcBottom = val;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void setModTCLeft(final float val) {
		modTcLeft = val;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void setModTCRight(final float val) {
		modTcRight = val;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void setModTCTop(final float val) {
		modTcTop = val;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void setModWidth(final int w) {
		// TODO Auto-generated method stub

	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void setModXl(final float val) {
		modXl = val;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void setModXr(final float val) {
		modXr = val;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void setModYb(final float val) {
		modYb = val;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void setModYt(final float val) {
		modYt = val;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void setPosition(final double x, final double y, final double z) {
		if (position != null) {
			position.set(x, y, z);
		} else {
			position = new SimpleVector3(x, y, z);
		}
	}
	public void setPosition(final double x1, final double y1,
			final double z, final int height,
			final int alignment) throws Exception {
		this.setPosition(x1, y1, z);
		if (numLines > 0) {
			FontsheetObject font =
					GameFont.getInstance().getFontById(fontRefId);
			font.setGlyph(' ');
			int lineHeight = font.getCharHeight();
			float x = 0;
			switch (alignment) {
			case GuiComponent.TOP:
				float y = height;
				// iterate from top to bottom, assigning position
				for (int i = 0; i < numLines; i++) {
					y -= lineHeight;
					try {
						lines[i].setPosition(x, y);
					} catch (Exception ex) {
						System.out.println("error1 with setPosition");
						System.out.println("trying to get line index " + i
									+ " but lines has " + lines.length
								+ " lines");
						System.out.println("but think there are " + numLines
									+ " lines");
						throw ex;
					}
				}
				break;
			case GuiComponent.BOTTOM:
				y = 0;
				// iterate from bottom to top
				for (int i = numLines - 1; i >= 0; i--) {
					try {
						lines[i].setPosition(x, y);
					} catch (Exception ex) {
						System.out.println("error2 with setPosition");
						System.out.println("trying to get line index " + i
									+ " but lines has " + lines.length
								+ " lines");
						System.out.println("but think there are " + numLines
									+ " lines");
						throw ex;
					}
					y += lineHeight;
				}
				break;
			default:
				// get the total height
				int totalHeight = 0;
				for (int i = 0; i < numLines; i++) {
					totalHeight += lineHeight;
				}
				y = (height - totalHeight) / 2;
				// iterate from bottom to top
				for (int i = numLines - 1; i >= 0; i--) {
					try {
						lines[i].setPosition(x, y);
					} catch (Exception ex) {
						System.out.println("error3 with setPosition");
						System.out.println("trying to get line index " + i
									+ " but lines has " + lines.length
								+ " lines");
						System.out.println("but think there are " + numLines
									+ " lines");
						throw ex;
					}
					y += lineHeight;
				}
				break;
			}
		}
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void setPosition(final SimpleVector3 v) {
		position = v;
	}
	/**
	 * Sets sprite group's position, relative to its alignment and height.
	 * @param v the {@link SimpleVector3}
	 * @param height the height
	 * @param alignment the alignment
	 * @throws Exception if an error occurs
	 */
	public void setPosition(final SimpleVector3 v, final int height,
			final int alignment) throws Exception {
		this.setPosition(v);
		if (numLines > 0) {
			FontsheetObject font =
					GameFont.getInstance().getFontById(fontRefId);
			font.setGlyph(' ');
			int lineHeight = font.getCharHeight();
			float x = 0;
			switch (alignment) {
			case GuiComponent.TOP:
				float y = height;
				// iterate from top to bottom, assigning position
				for (int i = 0; i < numLines; i++) {
					y -= lineHeight;
					lines[i].setPosition(x, y);
				}
				break;
			case GuiComponent.BOTTOM:
				y = 0;
				// iterate from bottom to top
				for (int i = numLines - 1; i >= 0; i--) {
					lines[i].setPosition(x, y);
					y += lineHeight;
				}
				break;
			default:
				// get the total height
				int totalHeight = 0;
				for (int i = 0; i < numLines; i++) {
					totalHeight += lineHeight;
				}
				y = (height - totalHeight) / 2;
				// iterate from bottom to top
				for (int i = numLines - 1; i >= 0; i--) {
					lines[i].setPosition(x, y);
					y += lineHeight;
				}
				break;
			}
		}
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void setTCBottom(final float val) {
		tcBottom = val;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void setTCLeft(final float val) {
		tcLeft = val;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void setTCRight(final float val) {
		tcRight = val;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void setTCTop(final float val) {
		tcTop = val;
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void setWidth(final int w) {
		// TODO Auto-generated method stub

	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void setX1(final float val) {
		// TODO Auto-generated method stub

	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void setX2(final float val) {
		// TODO Auto-generated method stub

	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void setX3(final float val) {
		// TODO Auto-generated method stub

	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void setY1(final float val) {
		// TODO Auto-generated method stub

	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void setY2(final float val) {
		// TODO Auto-generated method stub

	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void setY3(final float val) {
		// TODO Auto-generated method stub

	}
}
